Skip to content

Conversation

@montyly
Copy link
Contributor

@montyly montyly commented Jul 7, 2025

This PR is a WIP to add new cheatcode to medusa. The PR is not ready yet, but I am sharing it in case anyone has time to provide some feedback.

It's built on top of #618, so the code outside of chain/cheat_code_tracer.go / chain/standard_cheat_code_contract.go is not relevant to the PR.

Once I have stabilized everything, I will open individual PR to make the review easier + add the relevant documentation.

Open questions:

  • It's a bit unclear to me what is the proper way to do unit test on the cheatcode.
  • getDeployedCode would benefit from some logging to let the user knows if the targeted contract was not deployed, but I am not sure how to log this properly
  • I am not sure the logic to support expectRevert is the right approach. The cheatcode is a bit tricky given it's logic, so I had to modify the OnOpcode hook (cheat_code_tracer.go). It works by having expectRevert adding a placeholder variable, that basically means "once you execute the first opcode after returning from the targeted call, invert the value on the stack". If you have a cleaner idea on how to handle this one, let me know

The new cheatcodes:

  • getDeployedCode
  • assertTrue / assertFalse
  • assume
  • expectEmit (NOOP for now)
  • expectRevert (WIP)
  • assertEq (and variant)

@anishnaik
Copy link
Collaborator

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +816 to +820
// getCode: Retrieves the runtime bytecode for a contract
contract.addMethod("getDeployedCode", abi.Arguments{{Type: typeString}}, abi.Arguments{},
func(tracer *cheatCodeTracer, inputs []any) ([]any, *cheatCodeRawReturnData) {

contractPath := inputs[0].(string)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Declare output for getDeployedCode or drop returned value

The getDeployedCode cheatcode is registered with zero output arguments (abi.Arguments{}) but the handler returns []any{bytecode}. CheatCodeContract.Run ABI‑packs return values according to the declared outputs, so returning a value with no outputs causes packing to fail and the call always reverts. As written this cheatcode can never succeed. It should expose a bytes output or avoid returning data.

Useful? React with 👍 / 👎.

Comment on lines +1034 to +1038
return string(l.([]byte)) == string(r.([]byte))
case abi.FixedBytesTy:
lBytes := l.([32]byte)
rBytes := r.([32]byte)
return string(lBytes[:]) == string(rBytes[:])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid fixed-size byte assertion panic in assertEq

The abi.FixedBytesTy branch in assertEqGenerator casts both inputs to [32]byte. When the cheatcode is invoked for bytes4 (registered above), the values are [4]byte, so the type assertion panics with interface conversion: [4]uint8 is not [32]uint8. Any assertEq on non‑32‑byte fixed arrays will therefore crash the cheatcode. Use the ABI type’s Size to cast to the correct array or compare slices instead.

Useful? React with 👍 / 👎.

Comment on lines +257 to +264
stack := scope.StackData()
index := len(stack) - 1
return_value := stack[index]
if return_value.Eq(uint256.NewInt(0)) {
stack[index] = *uint256.NewInt(1)
} else {

if !return_value.Eq(uint256.NewInt(1)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge expectRevert fails to mutate EVM stack

When an expectRevert marker is detected, OnOpcode fetches the stack via scope.StackData() and assigns to stack[index]. StackData() returns a copy of the stack, so the write does not affect the actual EVM stack and the success flag pushed by CALL remains unchanged. Consequently the cheatcode never flips 0↔1 and cannot enforce expected reverts. The code needs to mutate the real stack (e.g. through the stack object) instead of a copy.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants